package com.zsguan.z.zhttp4andr;

import android.content.Context;

import com.zsguan.s.stools4andr.SUrlTool;
import com.zsguan.z.slogger4andr.ZLogger;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;

/**
 * Created by chshqiang on 15-8-11.
 * HttpURLConnection工具
 */
public class ZHttpUrlConnection {

    public static String post(String url, Map<String, String> params, int timeout1, int timeout2) {

        HttpURLConnection connection = null;
        InputStreamReader in = null;
        DataOutputStream dop = null;
        BufferedReader br = null;
        StringBuilder result = new StringBuilder();

        try {
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(timeout1);
            connection.setReadTimeout(timeout2);
            connection.setUseCaches(false);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Charset", "UTF-8");

            connection.connect();

            int responseCode = connection.getResponseCode();

            switch (responseCode) {
                case 200:
                    dop = new DataOutputStream(connection.getOutputStream());
                    dop.write(SUrlTool.getUrlForMap(params).getBytes("UTF-8"));
                    dop.flush();

                    in = new InputStreamReader(connection.getInputStream());
                    br = new BufferedReader(in);
                    String line;

                    while ((line = br.readLine()) != null) {
                        result.append(line);
                    }

                    break;
                case 400:
                case 401:
                case 402:
                case 403:
                case 404:
                case 405:
                    break;
                case 500:
                case 501:
                case 502:
                case 503:
                case 504:
                case 505:
                    break;
            }
        } catch (SocketTimeoutException e) {
            ZLogger.e("SocketTimeoutException");
            e.printStackTrace();
        } catch (MalformedURLException e) {
            ZLogger.e("MalformedURLException");
            e.printStackTrace();
        } catch (ProtocolException e) {
            ZLogger.e("ProtocolException");
            e.printStackTrace();
        } catch (IOException e) {
            ZLogger.e("IOException");
            e.printStackTrace();
        } finally {
            try {
                if (null != br) {
                    br.close();
                }

                if (null != in) {
                    in.close();
                }

                if (null != dop) {
                    dop.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (null != connection) {
                connection.disconnect();
            }
        }

        return result.toString();
    }

    public static void post(String url, Map<String, String> params, int timeout1) {
        HttpURLConnection connection = null;
        DataOutputStream dop = null;

        try {
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(timeout1);
            connection.setUseCaches(false);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Charset", "UTF-8");

            connection.connect();

            dop = new DataOutputStream(connection.getOutputStream());
            dop.write(SUrlTool.getUrlForMap(params).getBytes("UTF-8"));
            dop.flush();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            ZLogger.e("MalformedURLException");
            e.printStackTrace();
        } catch (ProtocolException e) {
            ZLogger.e("ProtocolException");
            e.printStackTrace();
        } catch (IOException e) {
            ZLogger.e("IOException");
            e.printStackTrace();
        } finally {
            try {
                if (null != dop) {
                    dop.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (null != connection) {
                connection.disconnect();
            }
        }
    }

    private static Certificate getCertificate(Context context, String name) throws CertificateException, IOException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream certInput = null;

        Certificate certificate;
        try {
            certInput = context.getAssets().open(name);
            certificate = cf.generateCertificate(certInput);
        } finally {
            if(certInput != null) {
                certInput.close();
            }

        }

        return certificate;
    }

    /**
     * 获得KeyStore.
     *
     * @param keyStorePath 密钥库路径
     * @param password     密码
     * @return 密钥库
     * @throws Exception
     */
    public static KeyStore getKeyStore(Context context, String password, String keyStorePath)
            throws Exception {
        // 实例化密钥库
        KeyStore ks = KeyStore.getInstance(/*"JKS"*/KeyStore.getDefaultType());
        // 获得密钥库文件流
        InputStream is = context.getAssets().open(keyStorePath);
        // 加载密钥库
        ks.load(is, password.toCharArray());
//        ks.load(null, null);
//        ks.setCertificateEntry("server", getCertificate(context, keyStorePath));
        ZLogger.i(ks.toString());
        // 关闭密钥库文件流
        is.close();
        return ks;
    }

    /**
     * 获得SSLSocketFactory.
     *
     * @param password       密码
     * @param keyStorePath   密钥库路径
     * @param trustStorePath 信任库路径
     * @return SSLSocketFactory
     * @throws Exception
     */
    public static SSLContext getSSLContext(Context context, String password,
                                           String keyStorePath, String trustStorePath) throws Exception {
        // 实例化密钥库
//        KeyManagerFactory keyManagerFactory = KeyManagerFactory
//                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
        // 获得密钥库
//        KeyStore keyStore = getKeyStore(context, password, keyStorePath);
        // 初始化密钥工厂
//        keyManagerFactory.init(keyStore, password.toCharArray());

        // 实例化信任库
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        // 获得信任库
        KeyStore trustStore = getKeyStore(context, password, trustStorePath);
        ZLogger.i(trustStore.toString());
        // 初始化信任库
        trustManagerFactory.init(trustStore);
        // 实例化SSL上下文
        SSLContext ctx = SSLContext.getInstance("TLS");
        // 初始化SSL上下文
        ctx.init(null, trustManagerFactory.getTrustManagers(), null);
//        ctx.init(keyManagerFactory.getKeyManagers(),
//                trustManagerFactory.getTrustManagers(), null);
        // 获得SSLSocketFactory
        return ctx;
    }

    /**
     * 初始化HttpsURLConnection.
     *
     * @param password       密码  bestvwin
     * @param keyStorePath   密钥库路径
     * @param trustStorePath 信任库路径
     * @throws Exception
     */
    public static void initHttpsURLConnection(Context context, String password,
                                              String keyStorePath, String trustStorePath) throws Exception {
        // 声明SSL上下文
        SSLContext sslContext = null;
        // 实例化主机名验证接口
        HostnameVerifier hnv = new MyHostnameVerifier();
        try {
            sslContext = getSSLContext(context, password, keyStorePath, trustStorePath);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        if (sslContext != null) {
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        }
        HttpsURLConnection.setDefaultHostnameVerifier(hnv);
    }

    /**
     * 发送请求.
     *
     * @param httpsUrl 请求的地址
     * @param xmlStr   请求的数据
     */
    public static void post(String httpsUrl, String xmlStr) {
        HttpsURLConnection urlCon = null;
        try {
            urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();
            urlCon.setDoInput(true);
            urlCon.setDoOutput(true);
            urlCon.setRequestMethod("POST");
            urlCon.setRequestProperty("Content-Length",
                    String.valueOf(xmlStr.getBytes().length));
            urlCon.setUseCaches(false);
            //设置为gbk可以解决服务器接收时读取的数据中文乱码问题
            urlCon.getOutputStream().write(xmlStr.getBytes("gbk"));
            urlCon.getOutputStream().flush();
            urlCon.getOutputStream().close();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    urlCon.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class MyHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            if ("localhost".equals(hostname)) {
                return true;
            } else {
                return false;
            }
        }
    }
}
